package com.micro.ai.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.micro.ai.auth.dto.RoleCreateRequest;
import com.micro.ai.auth.dto.RoleDTO;
import com.micro.ai.auth.dto.RoleUpdateRequest;
import com.micro.ai.auth.entity.Role;
import com.micro.ai.auth.entity.RoleMenu;
import com.micro.ai.auth.entity.UserRole;
import com.micro.ai.auth.mapper.RoleMapper;
import com.micro.ai.auth.mapper.RoleMenuMapper;
import com.micro.ai.auth.mapper.UserRoleMapper;
import com.micro.ai.auth.service.RoleService;
import com.micro.ai.commons.exception.BusinessException;
import com.micro.ai.commons.util.IdUtils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色服务实现
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;
    
    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RoleDTO createRole(RoleCreateRequest request) {
        // 检查角色编码是否已存在
        if (existsByCode(request.getCode())) {
            throw new BusinessException("角色编码已存在: " + request.getCode());
        }

        Role role = new Role();
        BeanUtils.copyProperties(request, role);
        
        // 设置默认值
        if (!StringUtils.hasText(role.getType())) {
            role.setType("custom");
        }
        if (!StringUtils.hasText(role.getStatus())) {
            role.setStatus("active");
        }
        if (role.getSortOrder() == null) {
            role.setSortOrder(0);
        }
        
        // 计算层级
        if (StringUtils.hasText(role.getParentId())) {
            Role parent = roleMapper.selectById(role.getParentId());
            if (parent != null) {
                role.setLevel(parent.getLevel() + 1);
            } else {
                role.setLevel(1);
            }
        } else {
            role.setLevel(0);
        }

        role.setCreatedAt(LocalDateTime.now());
        role.setUpdatedAt(LocalDateTime.now());
        
        roleMapper.insert(role);
        
        log.info("创建角色成功: roleId={}, code={}, name={}", role.getId(), role.getCode(), role.getName());
        
        return convertToDTO(role);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RoleDTO updateRole(String roleId, RoleUpdateRequest request) {
        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("角色不存在: " + roleId);
        }

        // 不允许修改系统角色
        if ("system".equals(role.getType())) {
            throw new BusinessException("不允许修改系统角色");
        }

        // 更新字段
        if (StringUtils.hasText(request.getName())) {
            role.setName(request.getName());
        }
        if (StringUtils.hasText(request.getDescription())) {
            role.setDescription(request.getDescription());
        }
        if (StringUtils.hasText(request.getStatus())) {
            role.setStatus(request.getStatus());
        }
        if (request.getSortOrder() != null) {
            role.setSortOrder(request.getSortOrder());
        }
        
        // 更新父角色
        if (request.getParentId() != null) {
            if (!request.getParentId().equals(role.getId())) { // 不能设置自己为父角色
                role.setParentId(request.getParentId());
                if (StringUtils.hasText(request.getParentId())) {
                    Role parent = roleMapper.selectById(request.getParentId());
                    if (parent != null) {
                        role.setLevel(parent.getLevel() + 1);
                    }
                } else {
                    role.setLevel(0);
                }
            }
        }

        role.setUpdatedAt(LocalDateTime.now());
        roleMapper.updateById(role);

        log.info("更新角色成功: roleId={}, name={}", roleId, role.getName());

        return convertToDTO(role);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRole(String roleId) {
        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("角色不存在: " + roleId);
        }

        // 不允许删除系统角色
        if ("system".equals(role.getType())) {
            throw new BusinessException("不允许删除系统角色");
        }

        // 检查是否有用户使用此角色
        LambdaQueryWrapper<UserRole> userRoleQuery = new LambdaQueryWrapper<>();
        userRoleQuery.eq(UserRole::getRoleId, roleId);
        long userCount = userRoleMapper.selectCount(userRoleQuery);
        if (userCount > 0) {
            throw new BusinessException("角色正在被使用，无法删除");
        }

        // 检查是否有子角色
        LambdaQueryWrapper<Role> childQuery = new LambdaQueryWrapper<>();
        childQuery.eq(Role::getParentId, roleId);
        long childCount = roleMapper.selectCount(childQuery);
        if (childCount > 0) {
            throw new BusinessException("存在子角色，无法删除");
        }

        // 注意：角色关联的菜单权限（role_menus）和 API 权限（role_api_permissions）
        // 会通过数据库外键的 ON DELETE CASCADE 自动删除

        // 删除角色
        roleMapper.deleteById(roleId);

        log.info("删除角色成功: roleId={}", roleId);
    }

    @Override
    public RoleDTO getRoleById(String roleId) {
        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("角色不存在: " + roleId);
        }
        return convertToDTO(role);
    }

    @Override
    public RoleDTO getRoleByCode(String code) {
        LambdaQueryWrapper<Role> query = new LambdaQueryWrapper<>();
        query.eq(Role::getCode, code);
        Role role = roleMapper.selectOne(query);
        if (role == null) {
            throw new BusinessException("角色不存在: " + code);
        }
        return convertToDTO(role);
    }

    @Override
    public Page<RoleDTO> listRoles(int pageNum, int pageSize, String tenantId, String keyword, String status) {
        Page<Role> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Role> query = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(tenantId)) {
            query.eq(Role::getTenantId, tenantId);
        }
        if (StringUtils.hasText(keyword)) {
            query.and(q -> q.like(Role::getName, keyword)
                    .or().like(Role::getCode, keyword)
                    .or().like(Role::getDescription, keyword));
        }
        if (StringUtils.hasText(status)) {
            query.eq(Role::getStatus, status);
        }
        
        query.orderByAsc(Role::getSortOrder).orderByDesc(Role::getCreatedAt);
        
        Page<Role> rolePage = roleMapper.selectPage(page, query);
        
        Page<RoleDTO> dtoPage = new Page<>(rolePage.getCurrent(), rolePage.getSize(), rolePage.getTotal());
        dtoPage.setRecords(rolePage.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList()));
        
        return dtoPage;
    }

    @Override
    public List<RoleDTO> getAllRoles(String tenantId) {
        LambdaQueryWrapper<Role> query = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(tenantId)) {
            query.eq(Role::getTenantId, tenantId);
        }
        query.eq(Role::getStatus, "active");
        query.orderByAsc(Role::getSortOrder);
        
        List<Role> roles = roleMapper.selectList(query);
        return roles.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 分配权限（已废弃）
     * 
     * 注意：新权限系统不再使用此方法。
     * 请使用以下新接口：
     * 1. 菜单权限分配：通过 role_menus 表管理
     * 2. API 权限分配：通过 role_api_permissions 表管理
     * 
     * @deprecated 使用新的权限分配接口
     */
    @Override
    @Deprecated
    @Transactional(rollbackFor = Exception.class)
    public void assignPermissions(String roleId, List<String> permissionIds) {
        log.warn("调用了已废弃的 assignPermissions 方法。请使用新权限系统：role_menus 或 role_api_permissions");
        throw new BusinessException("此方法已废弃，请使用新的权限分配接口");
    }

    /**
     * 移除权限（已废弃）
     * 
     * @deprecated 使用新的权限分配接口
     */
    @Override
    @Deprecated
    @Transactional(rollbackFor = Exception.class)
    public void removePermissions(String roleId, List<String> permissionIds) {
        log.warn("调用了已废弃的 removePermissions 方法。请使用新权限系统：role_menus 或 role_api_permissions");
        throw new BusinessException("此方法已废弃，请使用新的权限分配接口");
    }

    /**
     * 获取角色权限（已废弃）
     * 
     * @deprecated 使用新的权限查询接口：getRoleMenuIds
     */
    @Override
    @Deprecated
    public List<String> getRolePermissions(String roleId) {
        log.warn("调用了已废弃的 getRolePermissions 方法。请使用新权限系统：getRoleMenuIds");
        // 返回菜单ID列表作为权限
        return getRoleMenuIds(roleId);
    }

    @Override
    public List<RoleDTO> getUserRoles(String userId) {
        LambdaQueryWrapper<UserRole> query = new LambdaQueryWrapper<>();
        query.eq(UserRole::getUserId, userId);
        List<UserRole> userRoles = userRoleMapper.selectList(query);
        
        if (userRoles.isEmpty()) {
            return new ArrayList<>();
        }
        
        List<String> roleIds = userRoles.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());
        
        List<Role> roles = roleMapper.selectBatchIds(roleIds);
        return roles.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public boolean existsByCode(String code) {
        LambdaQueryWrapper<Role> query = new LambdaQueryWrapper<>();
        query.eq(Role::getCode, code);
        return roleMapper.selectCount(query) > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignMenus(String roleId, List<String> menuIds) {
        // 验证角色是否存在
        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("角色不存在: " + roleId);
        }
        
        // 删除现有的菜单关联
        roleMenuMapper.deleteByRoleId(roleId);
        
        // 如果没有菜单ID，直接返回
        if (menuIds == null || menuIds.isEmpty()) {
            log.info("清空角色菜单权限: roleId={}", roleId);
            return;
        }
        
        // 创建新的菜单关联
        List<RoleMenu> roleMenus = new ArrayList<>();
        for (String menuId : menuIds) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setId(IdUtils.generateId());
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            roleMenu.setCreatedAt(LocalDateTime.now());
            roleMenu.setUpdatedAt(LocalDateTime.now());
            roleMenus.add(roleMenu);
        }
        
        // 批量插入
        roleMenuMapper.batchInsert(roleMenus);
        log.info("为角色分配菜单权限: roleId={}, menuCount={}", roleId, menuIds.size());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeMenus(String roleId, List<String> menuIds) {
        if (menuIds == null || menuIds.isEmpty()) {
            return;
        }
        
        // 删除指定的菜单关联
        for (String menuId : menuIds) {
            LambdaQueryWrapper<RoleMenu> query = new LambdaQueryWrapper<>();
            query.eq(RoleMenu::getRoleId, roleId);
            query.eq(RoleMenu::getMenuId, menuId);
            roleMenuMapper.delete(query);
        }
        
        log.info("移除角色菜单权限: roleId={}, menuCount={}", roleId, menuIds.size());
    }
    
    @Override
    public List<String> getRoleMenuIds(String roleId) {
        return roleMenuMapper.selectMenuIdsByRoleId(roleId);
    }

    /**
     * 转换为DTO
     */
    private RoleDTO convertToDTO(Role role) {
        if (role == null) {
            return null;
        }
        RoleDTO dto = new RoleDTO();
        BeanUtils.copyProperties(role, dto);
        return dto;
    }
}

